﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using SlamCms.Common;

using System.IO;

namespace SlamCms.SharePoint
{
	public class ImageModule : IHttpModule
	{
		private HttpApplication currentContext = null;
		public void Dispose()
		{
		}

		public void Init(HttpApplication context)
		{
			currentContext = context;
			context.ReleaseRequestState += new EventHandler(context_ReleaseRequestState);
			context.PreSendRequestHeaders += new EventHandler(context_PreSendRequestHeaders);
		}

		protected void context_PreSendRequestHeaders(object sender, EventArgs e)
		{
			int imageWidth = 0;
			int imageHeight = 0;

			if (currentContext.Response.ContentType != null && currentContext.Response.ContentType.StartsWith("image/") &&
				currentContext.Request.QueryString["width"] != null &&
				currentContext.Request.QueryString["height"] != null &&
				Int32.TryParse(currentContext.Request.QueryString["width"], out imageWidth) &&
				Int32.TryParse(currentContext.Request.QueryString["height"], out imageHeight))
			{
				currentContext.Response.AddHeader("Content-Length", currentContext.Response.Filter.Length.ToString());
			}
		}

		protected void context_ReleaseRequestState(object sender, EventArgs e)
		{
			int imageWidth = 0;
			int imageHeight = 0;
			long jpegQuality = 100L;
			bool cropImage = false;
			bool alwaysProcess = false;

			if (currentContext.Response.ContentType.StartsWith("image/") &&
				currentContext.Request.QueryString["width"] != null &&
				currentContext.Request.QueryString["height"] != null &&
				Int32.TryParse(currentContext.Request.QueryString["width"], out imageWidth) &&
				Int32.TryParse(currentContext.Request.QueryString["height"], out imageHeight))
			{
				if (currentContext.Request.QueryString["crop"] != null)
				{
					Boolean.TryParse(currentContext.Request.QueryString["crop"], out cropImage);
				}

				if (currentContext.Request.QueryString["alwaysprocess"] != null)
				{
					Boolean.TryParse(currentContext.Request.QueryString["alwaysprocess"], out alwaysProcess);
				}

				if (currentContext.Request.QueryString["jpegquality"] != null)
				{
					Int64.TryParse(currentContext.Request.QueryString["jpegquality"], out jpegQuality);
				}
				currentContext.Response.Filter = new ResizeImageStream(currentContext.Response.Filter, imageWidth, imageHeight, cropImage, jpegQuality, alwaysProcess);
			}
		}

		public class ResizeImageStream : Stream
		{
			private Stream _stream;
			private MemoryStream _resizedStream = new MemoryStream();
			private long _position;

			private int _width;
			private int _height;
			private bool _cropImage;
			private long _jpegQuality;
			private long _length;
			private bool _alwaysProcess;

			public ResizeImageStream(Stream responseStream, int maxWidth, int maxHeight, bool cropImage, long jpegQuality, bool alwaysProcess)
			{
				_stream = responseStream;
				_width = maxWidth;
				_height = maxHeight;
				_cropImage = cropImage;
				_jpegQuality = jpegQuality;
				_alwaysProcess = alwaysProcess;
			}

			public override bool CanRead
			{
				get
				{
					return true;
				}
			}
		
			public override bool CanSeek
			{
				get 
				{ 
					return true; 
				}
			}

			public override bool CanWrite
			{
				get 
				{ 
					return true; 
				}
			}

			public override long Length
			{
				get 
				{ 
					return _length; 
				}
			}

			public override long Position
			{
				get 
				{ 
					return _position;
				}
				set 
				{ 
					_position = value;
				}
			}

			public override long Seek(long offset, SeekOrigin direction)
			{
				return _stream.Seek(offset, direction);
			}

			public override void SetLength(long length)
			{
				_stream.SetLength(length);
			}

			public override void Close()
			{
				_stream.Close();
			}

			public override void Flush()
			{
				if (_cropImage)
				{
					_resizedStream = ImageResizer.CropResizeImageFromStream(_resizedStream, _width, _height, _jpegQuality, _alwaysProcess) as MemoryStream;
				}
				else
				{
					_resizedStream = ImageResizer.ResizeImageFromStream(_resizedStream, _width, _height, _jpegQuality, _alwaysProcess) as MemoryStream;
				}

				_length = _resizedStream.Length;
				_stream.Write(_resizedStream.ToArray(), 0, (int)_length);
				_stream.Flush();
			}

			public override int Read(byte[] buffer, int offset, int count)
			{
				return _stream.Read(buffer, offset, count);
			}

			public override void Write(byte[] buffer, int offset, int count)
			{
				_resizedStream.Write(buffer, 0, count);
			}
		}
	}
}
